package com.cdqidi.controller;

import java.io.IOException;
import java.sql.SQLException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.cdqidi.entity.PayResult;
import com.cdqidi.entity.User;
import com.cdqidi.interceptor.WxVerInterceptor;
import com.cdqidi.model.OrgWxconfig;
import com.cdqidi.service.ApiConfigService;
import com.cdqidi.service.OrgWxConfigService;
import com.cdqidi.service.WeiXinPayService;
import com.cdqidi.service.WxAuthService;
import com.cdqidi.util.IPUtil;
import com.cdqidi.util.RandomCharData;
import com.cdqidi.util.RedisMgr;
import com.cdqidi.util.StaticResource;
import com.jfinal.aop.Before;
import com.jfinal.kit.HttpKit;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.ActiveRecordException;
import com.jfinal.weixin.sdk.api.ApiConfig;
import com.jfinal.weixin.sdk.api.PaymentApi;
import com.jfinal.weixin.sdk.api.PaymentApi.TradeType;
import com.jfinal.weixin.sdk.api.SnsAccessToken;
import com.jfinal.weixin.sdk.jfinal.ApiController;
import com.jfinal.weixin.sdk.kit.IpKit;
import com.jfinal.weixin.sdk.kit.PaymentKit;
import com.jfinal.weixin.sdk.utils.JsonUtils;

public class WeixinPayController extends ApiController{
	private static Logger logger = Logger.getLogger(WeixinPayController.class);
	
	private static String NOTIFY_URL = StaticResource.URL+"/wPay/pay/pay_notify";
	private final String ERRORURL="/WEB-INF/page/error/500.jsp";
	
	/**
	 * 下单,到微信端获得code
	 */
	@Before(WxVerInterceptor.class)
	public void unifiedOrder() {
		String wxorgid = getPara("wxorgid");
		String code = getPara("code");
		
		String id = getSessionAttr("wPay_user");
		String orderId;
		if(StringUtils.isEmpty(id)) {
			setAttr("errmsg", "会话超时，请重新进入购买页面");
			render(ERRORURL);
			return;
		}
		try {
			SnsAccessToken sns = WxAuthService.getInstance().getOpenid(code, wxorgid);
			String openid = sns.getOpenid();
			logger.info("从微信端获得openid： " + openid+",wxorgid: "+wxorgid);
			if(StringUtils.isEmpty(openid)) {
				setAttr("errmsg", "支付公众号获得用户唯一标识失败");
				render(ERRORURL);
				return;
			}
			
			String json = RedisMgr.getInstance().getProp(id);
			if(StringUtils.isEmpty(json)) {
				setAttr("errmsg", "会话超时，请重新进入购买页面");
				render(ERRORURL);
				return;
			}
			User user = JSON.parseObject(json, User.class);
			user.setPayOpenid(openid);
			
			OrgWxconfig config = OrgWxConfigService.getInstance().getWxConfig(wxorgid);
			Map<String, String> params = new HashMap<String, String>();
			params.put("appid", user.getAppId());
			params.put("mch_id", user.getMchId());
			params.put("body", user.getChargeInfo());
			orderId = System.currentTimeMillis()+RandomCharData.createRandomCharData(19);//订单号，唯一
			params.put("out_trade_no", orderId);
			params.put("total_fee", user.getAmount()+"");
			String ip = IpKit.getRealIp(getRequest());
			if (StrKit.isBlank(ip)) {
				ip = "127.0.0.1";
			}
			try {
		        ip = IPUtil.hexToIP(IPUtil.ipToHex(ip));
		    }catch (Exception ex){
		        ip = "127.0.0.1";
		    }
//			logger.info("商户订单号： " + orderId);
//			logger.info("unifiedOrder,ip: "+ip);
			
			params.put("spbill_create_ip", ip);
			params.put("trade_type", TradeType.JSAPI.name());
			params.put("nonce_str", System.currentTimeMillis()+ RandomCharData.createRandomCharData(12));
			params.put("notify_url", NOTIFY_URL);
			params.put("openid", openid);

			String sign = PaymentKit.createSign(params, user.getApiKey());
			params.put("sign", sign);
			String xmlResult = PaymentApi.pushOrder(params);
			
//			logger.info("xmlResult: "+xmlResult);
			Map<String, String> result = PaymentKit.xmlToMap(xmlResult);
			
			String return_code = result.get("return_code");
			String return_msg = result.get("return_msg");
			if (StrKit.isBlank(return_code) || !"SUCCESS".equals(return_code)) {
				setAttr("errmsg", return_msg);
				render(ERRORURL);
				return;
			}
			String result_code = result.get("result_code");
			if (StrKit.isBlank(result_code) || !"SUCCESS".equals(result_code)) {
				setAttr("errmsg", return_msg);
				render(ERRORURL);
				return;
			}
			// 以下字段在return_code 和result_code都为SUCCESS的时候有返回
			String prepay_id = result.get("prepay_id");
			Long timeStamp = System.currentTimeMillis();
			Map<String, String> packageParams = new HashMap<String, String>();
			packageParams.put("appId", config.getAppId());
			packageParams.put("timeStamp", timeStamp/ 1000 + "");
			packageParams.put("nonceStr", System.currentTimeMillis()+RandomCharData.createRandomCharData(19));
			packageParams.put("package", "prepay_id=" + prepay_id);
			packageParams.put("signType", "MD5");
			String packageSign = PaymentKit.createSign(packageParams, user.getApiKey());
			
			
			packageParams.put("paySign", packageSign);
			
			String jsonStr = JsonUtils.toJson(packageParams);
			
//			logger.info("jsonStr: "+jsonStr);
			
			setAttr("json", jsonStr);
			setAttr("orderId",orderId);
			setAttr("wxorgid",user.getWxorgid());
		
			//生成订单
			WeiXinPayService.getInstance().saveWxOrder(orderId, ip, jsonStr, new Date(timeStamp), user);
			
			renderJsp("/WEB-INF/page/pay.jsp");
		}catch (JSONException e) {
			logger.error(e);
			setAttr("errmsg", "系统错误");
			render(ERRORURL);
			return;
		}catch (ActiveRecordException e) {
			logger.error(e);
			setAttr("errmsg", "系统错误");
			render(ERRORURL);
			return;
		}catch (ClassNotFoundException | IOException e) {
			logger.error(e);
			setAttr("errmsg", "系统错误");
			render(ERRORURL);
			return;
		}catch (Exception e) {
			e.printStackTrace();
			logger.error(e);
			setAttr("errmsg", "系统错误");
			render(ERRORURL);
			return;
		}
		
	}
	@Before(WxVerInterceptor.class)
	public void sendUrl() {
		String id = getSessionAttr("wPay_user");
		String orderId = getPara("orderId");
		String state = getPara("state");
		User user = null;
		String url = null;
		try {
			if(StringUtils.isEmpty(id)) {
				setAttr("errmsg", "异常操作");
				render(ERRORURL);
				return;
			}
			String json = RedisMgr.getInstance().getProp(id);
			user = JSON.parseObject(json, User.class);
			//清理session，redis缓存
			RedisMgr.getInstance().delProp(id);
			getSession().removeAttribute("wPay_user");
			//更新状态
			WeiXinPayService.getInstance().updateWxOrderState(orderId, state);
		} catch (Exception e) {
			e.printStackTrace();
			logger.error(e);
		}
		
		try {
			if(state.equals("ok")) {
				if(null==user) {
					setAttr("errmsg", "未配置跳转页面");
					render(ERRORURL);
					return;
				}
				url=user.getUrl();
				if(StringUtils.isEmpty(url)) {
					renderNull();
				}
				if(url.indexOf("?")==-1) {
					url = url+"?orderId="+orderId;
				}else {
					url = url+"&orderId"+orderId;
				}
				System.out.println("url: "+url);
				getResponse().sendRedirect(url);
				renderNull();
			}else {
				setAttr("errmsg", "支付失败");
				render(ERRORURL);
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	@Override
	public ApiConfig getApiConfig() {
		String wxorgid = getPara("wxorgid");
		return ApiConfigService.getInstance().getApiConfig(wxorgid);
	}
	
	public void pay_notify() {
		String realIp = IpKit.getRealIp(getRequest());
		logger.info("pay_notify,Ip: "+realIp);
		
		String xmlMsg = HttpKit.readData(getRequest());
		logger.info("支付通知="+xmlMsg);
		if(StringUtils.isEmpty(xmlMsg)) {
			return;
		}
		
		Map<String, String> params = PaymentKit.xmlToMap(xmlMsg);
		String returnCode = params.get("return_code");
		if(StringUtils.isEmpty(returnCode)) {
			return;
		}
		System.out.println("return_code: "+returnCode);
		if(returnCode.equals("SUCCESS")) {
			String resultCode = params.get("result_code");
			//商户号
			String mchId = params.get("mch_id");
			//总金额
			String totalFee = params.get("total_fee");
			//商户订单号
			String orderId = params.get("out_trade_no");
			//微信支付订单号
			String transId = params.get("transaction_id");
			//支付完成时间
			String timeEnd = params.get("time_end");
			//支付银行
			String bankType = params.get("bank_type");
			Map<String, String> xml = new HashMap<String, String>();
			
			String paternerKey = WeiXinPayService.getInstance().getApiKey(mchId);
			if(StringUtils.isEmpty(paternerKey)) {
				logger.info("获得支付密钥失败，商户号: "+mchId);
			}
			if(PaymentKit.verifyNotify(params, paternerKey)){
				if (("SUCCESS").equals(resultCode)) {
					PayResult data = new PayResult();
					data.setMchId(mchId);
					data.setBankType(bankType);
					data.setResultCode(resultCode);
					Long _totalFee=0L;
					try {
						_totalFee = Long.parseLong(totalFee);
						Date _timeEnd = DateUtils.parseDate(timeEnd, "yyyyMMddHHmmss");
						data.setTimeEnd(_timeEnd);
					}catch (Exception e) {
						e.printStackTrace();
					}
					data.setTotalFee(_totalFee);
					data.setTransactionId(transId);
					data.setOutTradeNo(orderId);
					try {
						boolean b = WeiXinPayService.getInstance().saveWxOrderLog(data);
						if(b) {
							xml.put("return_code", "SUCCESS");
							xml.put("return_msg", "OK");
						}else {
							xml.put("return_code", "FAIL");
							xml.put("return_msg", "");
						}
					}catch (SQLException e) {
						xml.put("return_code", "FAIL");
						xml.put("return_msg", "");
					}
				}else {
					xml.put("return_code", "FAIL");
					xml.put("return_msg", "resultCode显示未FAIL");
					logger.info("返回code为失败： "+xmlMsg);
				}
			}else {
				xml.put("return_code", "FAIL");
				xml.put("return_msg", "签名效验失败");
			}
			renderText(PaymentKit.toXml(xml));
			return;
		}
		renderNull();
	}
}